package com.corx.network.mysqlstorage.repository;

import com.corx.network.mysqlstorage.common.JdbcPagingSupport;
import com.corx.network.mysqlstorage.common.PageQuery;
import com.corx.network.mysqlstorage.common.PageResult;
import com.corx.network.mysqlstorage.common.SqlQueryBuilder;
import com.corx.network.mysqlstorage.model.DevicePoint;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.lang.NonNull;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * 设备采集点/订阅点 JDBC Repository
 * @author gx
 * @version 1.0.0
 */
public class JdbcDevicePointRepository extends JdbcPagingSupport<DevicePoint> implements DevicePointRepository {

    public JdbcDevicePointRepository(JdbcTemplate jdbcTemplate) {
        super(jdbcTemplate);
    }

    @Override
    protected RowMapper<DevicePoint> getRowMapper() {
        return (rs, rowNum) -> {
            DevicePoint point = new DevicePoint();
            point.setId(rs.getLong("id"));
            point.setDeviceId(rs.getLong("device_id"));
            point.setParams(rs.getString("params"));
            point.setStatus(rs.getString("status"));
            point.setCreateTime(rs.getTimestamp("create_time"));
            point.setUpdateTime(rs.getTimestamp("update_time"));
            return point;
        };
    }

    @Override
    public Optional<DevicePoint> findById(@NonNull Long id) {
        List<DevicePoint> list = jdbcTemplate.query(
            "SELECT * FROM corx_device_point WHERE id = ?", getRowMapper(), id
        );
        return Optional.ofNullable(DataAccessUtils.singleResult(list));
    }

    @Override
    public List<DevicePoint> findByDeviceId(@NonNull Long deviceId) {
        return jdbcTemplate.query(
            "SELECT * FROM corx_device_point WHERE device_id = ?", getRowMapper(), deviceId
        );
    }

    @Override
    public List<DevicePoint> findByDeviceIds(@NonNull Collection<Long> deviceIds) {
        String sql = String.format(
            "SELECT * FROM corx_device_point WHERE device_id IN (%s)",
            String.join(",", Collections.nCopies(deviceIds.size(), "?"))
        );
        return jdbcTemplate.query(sql, getRowMapper(), deviceIds.toArray());
    }

    @Override
    public void save(@NonNull DevicePoint point) {
        String sql = "INSERT INTO corx_device_point (device_id, params, status, create_time, update_time) " +
                     "VALUES ( ?, ?, ?, NOW(), NOW())";
        jdbcTemplate.update(sql, point.getDeviceId(),  point.getParams(), point.getStatus());
    }

    @Override
    public void update(@NonNull DevicePoint point) {
        String sql = "UPDATE corx_device_point SET device_id = ?, params = ?, status = ?, update_time = NOW() WHERE id = ?";
        jdbcTemplate.update(sql, point.getDeviceId(), point.getParams(), point.getStatus(), point.getId());
    }

    @Override
    public void delete(@NonNull Long id) {
        jdbcTemplate.update("DELETE FROM corx_device_point WHERE id = ?", id);
    }

    @Override
    public PageResult<DevicePoint> findByPage(DevicePoint model, PageQuery pageQuery) {
        SqlQueryBuilder queryBuilder = new SqlQueryBuilder("SELECT * FROM corx_device_point");

        if (model.getDeviceId() != null) {
            queryBuilder.whereEquals("device_id", model.getDeviceId());
        }
        if (model.getStatus() != null && !model.getStatus().isEmpty()) {
            queryBuilder.whereEquals("status", model.getStatus());
        }
        if (pageQuery.hasSort()) {
            queryBuilder.orderBy(pageQuery.orderBy());
        }

        String baseSql = queryBuilder.getSql();
        Object[] params = queryBuilder.getParams();

        return super.findByPage(baseSql, params, pageQuery);
    }
}
